#pragma once


namespace zsw
{
	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr()
			: ptr(nullptr)
			, count(nullptr)
		{}

		shared_ptr(T* p)
			:ptr(p)
			,count(new int(1))
		
		{}

		template<class T, class D>
		shared_ptr(T* p, D d)
			: ptr(p)
			, count(new int(1))
			, del(d)
		{
		}


		shared_ptr(const shared_ptr<T>& o)
		{
			*this = o;
		}


		shared_ptr<T>& operator=(const shared_ptr<T>& o)
		{
			if (ptr == o.ptr)
			{
				return *this;
			}

			if (ptr != nullptr)
				this->destory();

			ptr = o.ptr;
			count = o.count;
			(*count)++;

			return *this;
		}


		T& operator*()
		{
			return *ptr;
		}

		T* operator->()
		{
			return ptr;
		}

		~shared_ptr()
		{
			destory();
		}
	private:
		void destory()
		{
			if (count == nullptr)
				return;

			(*count)--;


			if (*count == 0)
			{
				delete count;
				delete ptr;
				count = nullptr;
				del(p);
				return;
			}

		}

		std::functinal<void(T*)> del = [](T* p) {delete p; };
		int* count;
		T* ptr;
	};
}